
#include "vsf_hal.h"

// 1010 A2 A1 A0
#define E2PROM_ADDRESS    0x50
#define E2PROM_PAGE_SIZE  32
#define E2PROM_SLAVE_ADDR 0x48
#define I2C_DEMO_EEPROM_WRITE_ADDRES 0

#define I2C_DEMO_IRQ_MASK                                                      \
    VSF_I2C_IRQ_MASK_MASTER_ADDRESS_NACK | VSF_I2C_IRQ_MASK_MASTER_ERROR |     \
        VSF_I2C_IRQ_MASK_MASTER_NACK_DETECT |                                  \
        VSF_I2C_IRQ_MASK_MASTER_TRANSFER_COMPLETE


static struct {
    volatile bool is_cpl;
    uint8_t       address[2];
    uint8_t       send_buf[E2PROM_PAGE_SIZE];
    uint8_t       recv_buf[E2PROM_PAGE_SIZE];
} __i2c_demo;

static void __i2c_isrhandler(void *target_ptr, vsf_i2c_t *i2c_ptr,
                             vsf_i2c_irq_mask_t irq_mask)
{
    if (irq_mask & VSF_I2C_IRQ_MASK_MASTER_TRANSFER_COMPLETE) {
        __i2c_demo.is_cpl = true;
    } else {
        VSF_ASSERT(0);
    }
}

void vsf_i2c_eeprom_demo(void)
{
    vsf_err_t err = vsf_hw_i2c_init(
        &vsf_hw_i2c0, &(vsf_i2c_cfg_t){
                          .mode = VSF_I2C_MODE_MASTER |
                                  VSF_I2C_SPEED_FAST_MODE | VSF_I2C_ADDR_7_BITS,
                          .clock_hz = 100 * 1000,
                          .isr =
                              {
                                  .handler_fn = __i2c_isrhandler,
                                  .target_ptr = NULL,
                                  .prio       = vsf_arch_prio_0,
                              },
                      });
    VSF_ASSERT(err == VSF_ERR_NONE);

    while (fsm_rt_cpl != vsf_hw_i2c_enable(&vsf_hw_i2c0));

    vsf_hw_i2c_irq_enable(&vsf_hw_i2c0, I2C_DEMO_IRQ_MASK);

    __i2c_demo.address[0] = (I2C_DEMO_EEPROM_WRITE_ADDRES >> 8) & 0xFF;
    __i2c_demo.address[1] = (I2C_DEMO_EEPROM_WRITE_ADDRES >> 0) & 0xFF;
    for (int i = 0; i < E2PROM_PAGE_SIZE; i++) {
        __i2c_demo.send_buf[i] = i;
    }

    // i2c write address and data
    __i2c_demo.is_cpl = false;
    vsf_hw_i2c_master_request(&vsf_hw_i2c0, E2PROM_ADDRESS,
                              VSF_I2C_CMD_START | VSF_I2C_CMD_WRITE |
                                  VSF_I2C_CMD_7_BITS | VSF_I2C_CMD_STOP,
                              sizeof(__i2c_demo.address) +
                                  sizeof(__i2c_demo.send_buf),
                              __i2c_demo.address);
    while (!__i2c_demo.is_cpl);

    for (int i = 0; i < 100000; i++) {
        __NOP();
    }

    // i2c write address, then read data
    __i2c_demo.is_cpl = false;
    vsf_hw_i2c_master_request(&vsf_hw_i2c0, E2PROM_ADDRESS,
                              VSF_I2C_CMD_START | VSF_I2C_CMD_WRITE |
                                  VSF_I2C_CMD_7_BITS,
                              sizeof(__i2c_demo.address), __i2c_demo.address);
    while (!__i2c_demo.is_cpl);

    for (int i = 0; i < 10000; i++) {
        __NOP();
    }

    __i2c_demo.is_cpl = false;
    vsf_hw_i2c_master_request(&vsf_hw_i2c0, E2PROM_ADDRESS,
                              VSF_I2C_CMD_RESTART | VSF_I2C_CMD_READ |
                                  VSF_I2C_CMD_7_BITS | VSF_I2C_CMD_STOP,
                              sizeof(__i2c_demo.recv_buf), __i2c_demo.recv_buf);
    while (!__i2c_demo.is_cpl);
}
